package com.shanxia.codec.cmd;

import com.shanxia.codec.Decoder;
import com.shanxia.codec.ProtocolDataBase;
import com.shanxia.codec.enums.DecodeEnum;
import com.shanxia.codec.enums.PileUsableEnum;
import lombok.Data;

import java.util.Arrays;

import static com.shanxia.codec.Decoder.*;

/**
 * S -> C
 * 服务器应答充电桩签到命令
 * 后台服务器对收到充电桩签到报文后的应答
 * TODO demo中有少于151字节的例子
 */
@Data
public class Cmd105 extends ProtocolDataBase {

    public static final int MIN_SIZE = 151;

    private int v1;
    private int v2;
    private int randomReply;            //106 报文随机数应答
    private int loginVerify;            //登入验证
    private int encryptionSign;         //加密标志
    private String rsaModeNum;          //RSA 公共模数
    private int rsaSecretKey;           //RSA 公密
    private PileUsableEnum useSign;     //启停用标志
    private String standardTime;        //充电桩校时

    public Cmd105(){
        super.setCmd(105);
    }

    public static Cmd105 decodeFromBase(ProtocolDataBase protocolDataBase) {
        Cmd105 cmd = new Cmd105();
        cmd.copyDataFrom(protocolDataBase);
        byte[] dataField = protocolDataBase.getDataField();
        //数据域长度
        if (dataField.length < MIN_SIZE) {
            cmd.setResult(DecodeEnum.InvalidData);
            return cmd;
        }
        int offset = 0;
        cmd.v1 = getUint16(dataField, offset);
        offset += 2;
        cmd.v2 = getUint16(dataField, offset);
        offset += 2;
        // 4字节106 报文随机数应答
        cmd.randomReply = getInt32(dataField, offset);
        offset += 4;
        // 1字节登入验证
        cmd.loginVerify = getUint8(dataField[offset++]);
        // 1字节加密标志
        cmd.encryptionSign = getUint8(dataField[offset++]);
        // 128字节RSA公共模数
        cmd.rsaModeNum = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 128), false);
        offset += 128;
        // 4字节RSA公密
        cmd.rsaSecretKey = getInt32(dataField, offset);
        offset += 4;
        // 1字节启停用标志
        cmd.useSign = PileUsableEnum.getByCode(getUint8(dataField[offset++]));
        // 8字节平台标准BCD时间
        cmd.standardTime = Decoder.getStandardTime(dataField, offset);
        return cmd;
    }

    @Override
    public byte[] getDataField() {
        int offset = 0;
        byte[] data = new byte[MIN_SIZE];
        getBytesAsUint16(data, offset, this.v1);
        offset += 2;
        getBytesAsUint16(data, offset, this.v2);
        offset += 2;
        // 4字节106 报文随机数应答
        intToBytesLittle(data, offset, this.randomReply);
        offset += 4;
        // 1字节登入验证
        data[offset++] = (byte) this.loginVerify;
        // 1字节加密标志
        data[offset++] = (byte) this.encryptionSign;
        // 128字节RSA 公共模数
        encodeAscii(data, this.rsaModeNum, 128, offset);
        offset += 128;
        // 4字节RSA 公密
        intToBytesLittle(data, offset, this.rsaSecretKey);
        offset += 4;
        // 1字节启停用标志
        data[offset++] = (byte) this.useSign.code;
        // 8字节平台标准 BCD 时间
        encodeBasicTime(standardTime, data, offset, true);
        return data;
    }
}
